package vues;


import java.awt.Color;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;

import logique.preferences.CritereItineraireCourt;
import logique.preferences.CritereItineraireRapide;
import logique.reseau.Ville;

import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator;

public class PanelPrefSimples extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5896108408365567805L;

	// ATTRIBUTES //
	private boolean verbose = false;
	private InterfacePrincipale gps;
	
	public int listeSuppr = 1;
	public String villeDepartCourante = null;
	public String villeArriveeCourante = null;
	
	private javax.swing.ButtonGroup groupeBoutonChemin;
	private javax.swing.ButtonGroup groupeBoutonVillesInter;
	private javax.swing.JButton boutonLancerNavigation;
	private javax.swing.JButton boutonPrefAvancees;
	private javax.swing.JComboBox comboChoixReseau;
	private javax.swing.JLabel labelChoixItineraire;
	private javax.swing.JLabel labelVilleDepart;
	private javax.swing.JLabel labelVilleArrivee;
	private javax.swing.JLabel labelChemin;
	private javax.swing.JComboBox comboVilleDepart;
	private javax.swing.JComboBox comboVilleArrivee;
	private javax.swing.JLabel labelChoixVillesInter;
	private javax.swing.JRadioButton radioLePlusRapide;
	private javax.swing.JRadioButton radioLePlusCourt;
	private javax.swing.JRadioButton radioSans;
	private javax.swing.JRadioButton radioAvec;
	private javax.swing.JPanel panelVillesInter;

	public JList listeChoixTypeVilleOui;
	private JScrollPane scrollPaneChoixTypeVilleOui;
	public JList listeChoixTypeVille;
	private JScrollPane scrollPaneChoixTypeVille;
	public JList listeChoixTypeVilleNon;
	private JScrollPane scrollPaneChoixTypeVilleNon;
	
	public String listeOrigine;
	public boolean isDragging = false;
	public JList origineDragging = null;
	public JList listeSurvol = null;

	private JLabel labelChoixReseau;
	private String reseauCourant;

	protected boolean chargement;
	protected boolean actionDepart = false;
	protected boolean actionArrivee = false;
	private boolean ignore = false;
	
	protected LinkedList<String> contenuComboDepart;
	protected LinkedList<String> contenuComboArrivee;
	protected LinkedList<String> contenuListeInter;
	protected LinkedList<String> contenuListeInterOui;
	protected LinkedList<String> contenuListeInterNon;

	private PanelPrefAvancees panelPrefAvancees;
	
	// METHODS //
	public PanelPrefSimples(InterfacePrincipale gps) {
		// Enregistrement de la reference sur la fenetre principale
		this.gps = gps;
		
		// Initialisation du panel
		groupeBoutonChemin = new javax.swing.ButtonGroup();
		groupeBoutonVillesInter = new javax.swing.ButtonGroup();
		labelChoixItineraire = new javax.swing.JLabel();
		labelChoixReseau = new javax.swing.JLabel();
		labelVilleDepart = new javax.swing.JLabel();
		comboVilleDepart = new javax.swing.JComboBox();
		labelVilleArrivee = new javax.swing.JLabel();
		comboVilleArrivee = new javax.swing.JComboBox();
		labelChemin = new javax.swing.JLabel();
		radioLePlusRapide = new javax.swing.JRadioButton();
		radioLePlusCourt = new javax.swing.JRadioButton();
		boutonLancerNavigation = new javax.swing.JButton();
		boutonPrefAvancees = new javax.swing.JButton();
		labelChoixVillesInter = new javax.swing.JLabel();
		radioSans = new javax.swing.JRadioButton();
		radioAvec = new javax.swing.JRadioButton();
		comboChoixReseau = new javax.swing.JComboBox();
		panelVillesInter = new javax.swing.JPanel();
		listeChoixTypeVilleOui = new JList();
		scrollPaneChoixTypeVilleOui = new JScrollPane();
		listeChoixTypeVille = new JList();
		scrollPaneChoixTypeVille = new JScrollPane();
		listeChoixTypeVilleNon = new JList();
		scrollPaneChoixTypeVilleNon = new JScrollPane();
		chargement = true;
		
		this.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
		
		labelChoixReseau.setText("Choix du réseau:");
		this.add(labelChoixReseau, new org.netbeans.lib.awtextra.AbsoluteConstraints(80, 10, -1, -1));
		
		// Ajouter la liste des reseaux deja enregistres
		DefaultComboBoxModel comboReseauModel = new DefaultComboBoxModel();
		
		comboChoixReseau.setModel(comboReseauModel);
		AutoCompleteDecorator.decorate(comboChoixReseau);
		this.add(comboChoixReseau, new org.netbeans.lib.awtextra.AbsoluteConstraints(250, 10, -1, -1));
		
		labelChoixItineraire.setText("Choix de votre itin\u00e9raire:");
		this.add(labelChoixItineraire, new org.netbeans.lib.awtextra.AbsoluteConstraints(80, 40, -1, -1));

		labelVilleDepart.setText("Ville de d\u00e9part:");
		this.add(labelVilleDepart, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 70, -1, -1));
		
		// Liste �viter choix type ville
		ArrayListTransferHandlerPrefSimples listeChoixTypeVilleNonHandler = new ArrayListTransferHandlerPrefSimples(this);
		DefaultListModel listeChoixTypeVilleNonModel = new DefaultListModel();
		listeChoixTypeVilleNon = new JList(listeChoixTypeVilleNonModel);
		listeChoixTypeVilleNon.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		listeChoixTypeVilleNon.setTransferHandler(listeChoixTypeVilleNonHandler);
		listeChoixTypeVilleNon.setDragEnabled(true);
		listeChoixTypeVilleNon.setName("listeChoixTypeVilleNon");
		scrollPaneChoixTypeVilleNon.setViewportView(listeChoixTypeVilleNon);
		this.add(scrollPaneChoixTypeVilleNon, new org.netbeans.lib.awtextra.AbsoluteConstraints(280, 140, 170, 70));
		
		// Icone suivre choix type ville
		ImageIcon iconChoixTypeVilleOui = new ImageIcon(PanelPrefSimples.class.getResource("/fleches/passe_par3trans.png"));
		JLabel labelChoixTypeVilleOui = new JLabel(iconChoixTypeVilleOui);
		this.add(labelChoixTypeVilleOui, new org.netbeans.lib.awtextra.AbsoluteConstraints(185, 165, 80, -1));
		
		// Icone �viter choix type ville
		ImageIcon iconChoixTypeVilleNon = new ImageIcon(PanelPrefSimples.class.getResource("/fleches/evite3trans.png"));
		JLabel labelChoixTypeVilleNon = new JLabel(iconChoixTypeVilleNon);
		this.add(labelChoixTypeVilleNon, new org.netbeans.lib.awtextra.AbsoluteConstraints(185, 80, 80, -1));

		// Liste suivre choix type ville
		ArrayListTransferHandlerPrefSimples listeChoixTypeVilleOuiHandler = new ArrayListTransferHandlerPrefSimples(this);
		DefaultListModel listeChoixTypeVilleOuiModel = new DefaultListModel();
		listeChoixTypeVilleOui = new JList(listeChoixTypeVilleOuiModel);
		listeChoixTypeVilleOui.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		listeChoixTypeVilleOui.setTransferHandler(listeChoixTypeVilleOuiHandler);
		listeChoixTypeVilleOui.setDragEnabled(true);
		listeChoixTypeVilleOui.setName("listeChoixTypeVilleOui");
		scrollPaneChoixTypeVilleOui.setViewportView(listeChoixTypeVilleOui);
		this.add(scrollPaneChoixTypeVilleOui, new org.netbeans.lib.awtextra.AbsoluteConstraints(280, 60, 170, 70));
		
		// Liste choix type ville
		ArrayListTransferHandlerPrefSimples listeChoixTypeVilleHandler = new ArrayListTransferHandlerPrefSimples(this);
		DefaultListModel listeChoixTypeVilleModel = new DefaultListModel();
		listeChoixTypeVille = new JList(listeChoixTypeVilleModel);
		
		// Champ d'auto completion
		JTextField field = new JTextField();
		AutoCompleteDecorator.decorate(listeChoixTypeVille, field);
		
		listeChoixTypeVille.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		listeChoixTypeVille.setTransferHandler(listeChoixTypeVilleHandler);
		listeChoixTypeVille.setDragEnabled(true);
		listeChoixTypeVille.setName("listeChoixTypeVille");
		scrollPaneChoixTypeVille.setViewportView(listeChoixTypeVille);
		this.add(scrollPaneChoixTypeVille, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 80, 170, 70));
		
		comboVilleDepart.setModel(new DefaultComboBoxModel(new String[] {}));
		AutoCompleteDecorator.decorate(comboVilleDepart);
		comboVilleDepart.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				
				if (chargement) return;
				
				String tempVille = new String(updateVilleDepartArrivee(villeDepartCourante, villeArriveeCourante, comboVilleDepart, comboVilleArrivee));
				if (tempVille != null) villeDepartCourante = tempVille;
			}

		});
		
		
		this.add(comboVilleDepart, new org.netbeans.lib.awtextra.AbsoluteConstraints(250, 70, -1, -1));
		
		labelVilleArrivee.setText("Ville d'arriv\u00e9e:");
		this.add(labelVilleArrivee, new org.netbeans.lib.awtextra.AbsoluteConstraints(160, 350, -1, 20));
		
		comboVilleArrivee.setModel(new DefaultComboBoxModel(new String[] {}));
		AutoCompleteDecorator.decorate(comboVilleArrivee);
		comboVilleArrivee.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				
				if (chargement) return;
				
//				String tempVille = new String(updateVilleDepartArrivee(villeArriveeCourante, villeDepartCourante, comboVilleArrivee, comboVilleDepart));
//				if (tempVille != null) villeArriveeCourante = tempVille;
			}
			
		});

		this.add(comboVilleArrivee, new org.netbeans.lib.awtextra.AbsoluteConstraints(250, 350, -1, -1));

		labelChemin.setText("Chemin:");
		this.add(labelChemin, new org.netbeans.lib.awtextra.AbsoluteConstraints(190, 110, -1, -1));

		groupeBoutonChemin.add(radioLePlusRapide);
		radioLePlusRapide.setSelected(true);
		radioLePlusRapide.setText("le plus rapide");
		radioLePlusRapide.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		radioLePlusRapide.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.add(radioLePlusRapide, new org.netbeans.lib.awtextra.AbsoluteConstraints(300, 110, -1, -1));

		groupeBoutonChemin.add(radioLePlusCourt);
		radioLePlusCourt.setText("le plus court");
		radioLePlusCourt.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		radioLePlusCourt.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.add(radioLePlusCourt, new org.netbeans.lib.awtextra.AbsoluteConstraints(460, 110, -1, -1));

		boutonLancerNavigation.setText("Lancer la navigation");
		boutonLancerNavigation.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				sourisNav1(evt);
			}
		});

		this.add(boutonLancerNavigation, new org.netbeans.lib.awtextra.AbsoluteConstraints(640, 420, -1, -1));

		boutonPrefAvancees.setText("Pr\u00e9f\u00e9rences avanc\u00e9es");
		boutonPrefAvancees.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				sourisPref(evt);
			}
		});

		this.add(boutonPrefAvancees, new org.netbeans.lib.awtextra.AbsoluteConstraints(470, 420, -1, -1));

		labelChoixVillesInter.setText("Choix des villes interm\u00e9diaires:");
		this.add(labelChoixVillesInter, new org.netbeans.lib.awtextra.AbsoluteConstraints(80, 140, -1, -1));

		groupeBoutonVillesInter.add(radioSans);
		radioSans.setSelected(true);
		radioSans.setText("Sans");
		radioSans.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		radioSans.setMargin(new java.awt.Insets(0, 0, 0, 0));
		radioSans.addChangeListener(new javax.swing.event.ChangeListener() {
			public void stateChanged(javax.swing.event.ChangeEvent evt) {
				jRadioButtonSansChanged(evt);
			}
		});
		this.add(radioSans, new org.netbeans.lib.awtextra.AbsoluteConstraints(300, 140, -1, -1));

		groupeBoutonVillesInter.add(radioAvec);
		radioAvec.setText("Avec");
		radioAvec.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		radioAvec.setMargin(new java.awt.Insets(0, 0, 0, 0));
		radioAvec.addChangeListener(new javax.swing.event.ChangeListener() {
			public void stateChanged(javax.swing.event.ChangeEvent evt) {
				jRadioButtonAvecChanged(evt);
			}
		});

		this.add(radioAvec, new org.netbeans.lib.awtextra.AbsoluteConstraints(460, 140, -1, -1));
		
		panelVillesInter.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
		panelVillesInter.setVisible(false);
		panelVillesInter.add(field, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 0, 70, -1));
		panelVillesInter.add(scrollPaneChoixTypeVille, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 20, 160, 140));
		panelVillesInter.add(labelChoixTypeVilleNon, new org.netbeans.lib.awtextra.AbsoluteConstraints(155, 120, 80, -1));
		panelVillesInter.add(scrollPaneChoixTypeVilleNon, new org.netbeans.lib.awtextra.AbsoluteConstraints(220, 20, 130, 60));
		panelVillesInter.add(labelChoixTypeVilleOui, new org.netbeans.lib.awtextra.AbsoluteConstraints(155, 40, 80, -1));
		panelVillesInter.add(scrollPaneChoixTypeVilleOui, new org.netbeans.lib.awtextra.AbsoluteConstraints(220, 100, 130, 60));

		this.add(panelVillesInter, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 160, 380, 180));
		
		// Mise a jour de la liste des reseaux
		LinkedList<String> reseaux = this.gps.controleur.reseauxDisponibles();
//		if (reseaux.size() == 0) {
//			// Aucun r�seau dispo, on en ajoute au moins un
//			try {
//				File fichierReseau = this.gps.controleur.importReseau();
//				//this.gps.controleur.choisirReseau(fichierReseau.getAbsolutePath());
//				reseauCourant = fichierReseau.getName();
//				if (verbose) System.out.println("Ajout reseau nouveau : " + reseauCourant);
//				choixNouveauReseau();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		} else {
		
		if (reseaux.size() != 0) {
			// Un r�seau a d�ja �t� enregistr� on choisit le 1er par d�faut
			reseauCourant = reseaux.getFirst();
			for (String reseau : reseaux) {
				if (verbose) System.out.println("Ajout reseau existant : " + reseau);
				// On recupere le path du fichier XML (solution multiplateforme)
				comboReseauModel.addElement(reseau.substring(reseau.lastIndexOf(File.separator) + 1, reseau.length()));
			}
			choixNouveauReseau();
		}
//		}

		// Ajout d'un action listener sur la liste des r�saux
		comboChoixReseau.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				demanderNouveauReseau();
			}
		});
		
		chargement = false;
	}
	
	private String updateVilleDepartArrivee(String villePrecedente, String villeOpposee, JComboBox comboChanger, JComboBox comboChanged) {

		if (ignore) {
			ignore = false;
			return null;
		}
		
		DefaultListModel model = (DefaultListModel) listeChoixTypeVille.getModel();
		DefaultComboBoxModel comboModel = null;
		if (villePrecedente != null) {
			// Une ville courante a deja ete selectionnee
			
			// On la retablit dans la liste opposee
			ignore = true;
			comboChanged.addItem(villePrecedente);
			
			// On la retablit dans la liste des villes inter
			model.addElement(villePrecedente);

			// On rearrange comboChanged
			String[] c = new String[comboChanged.getItemCount()];
			for (int i=0; i<comboChanged.getItemCount(); i++){
				c[i] = (String) comboChanged.getModel().getElementAt(i);
			}
			java.util.Arrays.sort(c) ;

			// On reaffecte la liste des villes arrivee
			ignore = true;
			comboChanged.removeAllItems();
			for (int i=0; i<c.length; i++){
				ignore = true;
				comboChanged.addItem(c[i]);
			}
			// Si rien n'est selectionn�, on laisse rien selectionn�
			if (villeOpposee == null) comboChanged.setSelectedIndex(-1);
			else comboChanged.setSelectedItem(villeOpposee);

			// On rearrange les villes inter
			String[] c2 = new String[model.getSize()];
			for (int i=0; i<model.getSize(); i++){
				c2[i] = (String) model.get(i);
			}
			java.util.Arrays.sort(c2) ;

			//on reaffecte la liste
			model.removeAllElements();
			for (int i=0; i<c2.length; i++){
				model.addElement(c2[i]);
			}
		}

		// On recupere la nouvelle ville de d�part
		comboModel = (DefaultComboBoxModel) comboChanger.getModel();
		String nouvelleVille = (String) comboModel.getSelectedItem();
		
		// On le supprime de la liste oppos�e et si c'�tait l'�l�ment selectionne, on le deselectionne
//		if (comboChanged.getSelectedItem().equals(comboModel.getSelectedItem())) {
//			System.out.println("On deselectionne celui deja choisi");
//			ignore = true;
//			comboChanged.setSelectedIndex(-1);
//		}
		
		ignore = true;
		comboChanged.removeItem(nouvelleVille);
		
		// De la liste des villes inter
		model.removeElement(nouvelleVille);
		
		// On supprime la nouvelle ville selectionn�e des listes inter
		DefaultListModel modelInter = (DefaultListModel) listeChoixTypeVille.getModel();
		modelInter.removeElement(nouvelleVille);
		modelInter = (DefaultListModel) listeChoixTypeVilleNon.getModel();
		modelInter.removeElement(nouvelleVille);
		modelInter = (DefaultListModel) listeChoixTypeVilleOui.getModel();
		modelInter.removeElement(nouvelleVille);
		
		// On met a jour la ville courante
		ignore = false;
		return nouvelleVille;
	}
	
	public void ajouterReseauAdmin(String reseau) {
		// Un r�seau a �t� cr�� dans l'interface admin on le charge
		DefaultComboBoxModel comboReseauModel = (DefaultComboBoxModel) comboChoixReseau.getModel();
		comboReseauModel.addElement(reseau.substring(reseau.lastIndexOf(File.separator) + 1, reseau.length()));
		comboReseauModel.setSelectedItem(reseau.substring(reseau.lastIndexOf(File.separator) + 1, reseau.length()));
		
		// On actualise l'interface
		choixNouveauReseau();
	}
	
	public void modifierReseauAdmin(String reseau) {
		// Un r�seau a �t� selectionn� dans l'interface admin on le charge
		DefaultComboBoxModel comboReseauModel = (DefaultComboBoxModel) comboChoixReseau.getModel();
		comboReseauModel.setSelectedItem(reseau.substring(reseau.lastIndexOf(File.separator) + 1, reseau.length()));
		
		// On actualise l'interface
		choixNouveauReseau();
	}
	
	public void supprimerReseauAdmin(String reseauSuppr, String reseauNouveau) {
		// Un r�seau a �t� supprim� dans l'interface admin on le vire
		DefaultComboBoxModel comboReseauModel = (DefaultComboBoxModel) comboChoixReseau.getModel();
		comboReseauModel.removeElement(reseauSuppr.substring(reseauSuppr.lastIndexOf(File.separator) + 1, reseauSuppr.length()));
		
		// On ajoute le nouveau r�seau si il y en a un
		if (reseauNouveau != null) {
			comboReseauModel.addElement(reseauNouveau.substring(reseauNouveau.lastIndexOf(File.separator) + 1, reseauNouveau.length()));
			comboReseauModel.setSelectedItem(reseauNouveau.substring(reseauNouveau.lastIndexOf(File.separator) + 1, reseauNouveau.length()));
			
			// On actualise l'interface
			choixNouveauReseau();
		} else {
			viderListesApresSuppressionAdmin();
		}
		
		comboReseauModel.setSelectedItem(null);
	}
	
	public boolean chargerReseau(String reseau) {
		if (this.gps.panelNavigation.isSurLaRoute()) return false;
		else {
			gps.controleur.choisirReseau(reseau);
			return false;
		}
	}
	
	private void demanderNouveauReseau() {
		// Notifier interface administration
		if (comboChoixReseau.getSelectedIndex() == -1) return;
		
		String nouveauReseau = this.gps.controleur.reseauxDisponibles().get(comboChoixReseau.getSelectedIndex());
		if (!this.gps.panelAdministration.chargerReseau(nouveauReseau)) {
			// Impossible de changer le r�seau des modifs 
			JFrame frame = new JFrame("Conflit");
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			JOptionPane.showMessageDialog(frame, "Impossible de passer sur un autre réseau, un administrateur est en train de le modifier");
			return;
		}
		
		// On met a jour le r�seau dans le panel interface simple
		choixNouveauReseau();
	}
	
	private void viderListesApresSuppressionAdmin() {
		// Supprimer les villes deja choisies depart/arrivee et suivre/eviter
		DefaultComboBoxModel comboModelArrivee;
		DefaultComboBoxModel comboModelDepart;
		DefaultListModel listeModel;
		listeModel = (DefaultListModel) this.listeChoixTypeVille.getModel();
		listeModel.removeAllElements();
		
		listeModel = (DefaultListModel) this.listeChoixTypeVilleOui.getModel();
		listeModel.removeAllElements();
		
		listeModel = (DefaultListModel) this.listeChoixTypeVilleNon.getModel();
		listeModel.removeAllElements();
		
		comboModelArrivee = (DefaultComboBoxModel) this.comboVilleArrivee.getModel();
		comboModelArrivee.removeAllElements();
		
		comboModelDepart = (DefaultComboBoxModel) this.comboVilleDepart.getModel();
		comboModelDepart.removeAllElements();
	}
	
	private void choixNouveauReseau() {
		// Ici il faut mettre a jour l'interface pour le nouveau r�seau
		
		chargement = true;
		
		// Supprimer les villes deja choisies depart/arrivee et suivre/eviter
		DefaultComboBoxModel comboModelArrivee;
		DefaultComboBoxModel comboModelDepart;
		DefaultListModel listeModel;
		listeModel = (DefaultListModel) this.listeChoixTypeVille.getModel();
		listeModel.removeAllElements();
		
		listeModel = (DefaultListModel) this.listeChoixTypeVilleOui.getModel();
		listeModel.removeAllElements();
		
		listeModel = (DefaultListModel) this.listeChoixTypeVilleNon.getModel();
		listeModel.removeAllElements();
		
		comboModelArrivee = (DefaultComboBoxModel) this.comboVilleArrivee.getModel();
		comboModelArrivee.removeAllElements();
		
		comboModelDepart = (DefaultComboBoxModel) this.comboVilleDepart.getModel();
		comboModelDepart.removeAllElements();
		
		listeModel = (DefaultListModel) this.listeChoixTypeVille.getModel();
		Hashtable<String, Ville> villes = this.gps.controleur.getVilles();
		if (verbose) System.out.println("nbVilles = " + villes.size());
		String[] c = new String[villes.size()];
		int j = 0;
		for (String key : villes.keySet()) {
			if (verbose) System.out.println("Ville : " + key);
			c[j] = key;
			j++;
		}
		java.util.Arrays.sort(c) ;
		for (int i=0; i<c.length; i++){
			listeModel.addElement(c[i]);
			comboModelArrivee.addElement(c[i]);
			comboModelDepart.addElement(c[i]);
		}
		
		// None should be selected
		comboVilleDepart.setSelectedIndex(-1);
		villeDepartCourante = null;
		comboVilleArrivee.setSelectedIndex(-1);
		villeArriveeCourante = null;
		
		chargement = false;
	}
	
	/*
	private void sourisVilleDepart(java.awt.event.ActionEvent evt) {
		
		if (chargement) return;
		
//		if (actionArrivee) {
//			actionArrivee = false;
//			return;
//		}
		
		if (evt.getActionCommand().equals("comboBoxChanged")){
			// On rajoute la ville precedente
			DefaultListModel model = (DefaultListModel) listeChoixTypeVille.getModel();
			if (villeDepartCourante != null){
				comboVilleArrivee.addItem(villeDepartCourante);
				model.addElement(villeDepartCourante);
				
				// On rearrange comboVilleArrivee
				String[] c = new String[comboVilleArrivee.getItemCount()];
				for (int i=0; i<comboVilleArrivee.getItemCount(); i++){
						c[i] = (String) comboVilleArrivee.getModel().getElementAt(i);
				}
				java.util.Arrays.sort(c) ;
				
				// On reaffecte la liste
				comboVilleArrivee.removeAllItems();
				
				// On supprime la nouvelle ville selectionn�e des listes inter
				DefaultComboBoxModel comboModel = (DefaultComboBoxModel) comboVilleArrivee.getModel();
				System.out.println("On supprime la ville courante : " + comboVilleArrivee.getSelectedIndex());
				DefaultListModel modelInter = (DefaultListModel) listeChoixTypeVilleNon.getModel();
				modelInter.removeElement(villeDepartCourante);
				modelInter = (DefaultListModel) listeChoixTypeVilleOui.getModel();
				modelInter.removeElement(villeDepartCourante);
				
				for (int i=0; i<c.length; i++){
					comboVilleArrivee.addItem(c[i]);
				}
				
				// On rearrange comboVillesInter
				String[] c2 = new String[model.getSize()];
				for (int i=0; i<model.getSize(); i++){
						c2[i] = (String) model.get(i);
				}
				java.util.Arrays.sort(c2) ;
				
				//on reaffecte la liste
				model.removeAllElements();
				
				for (int i=0; i<c2.length; i++){
					model.addElement(c2[i]);
				}
			}
			
			actionDepart = true;
			
			//on recupere la nouvelle
			Object val = comboVilleDepart.getItemAt(comboVilleDepart.getSelectedIndex());
			//on l ajoute
			comboVilleArrivee.removeItem(val);
			model.removeElement(val);
			//on met a jour la ville courante
			villeDepartCourante = (String) val;
		}
	}
	
	private void sourisVilleArrivee(java.awt.event.ActionEvent evt) {
		
		if (chargement) return;
		
//		if (actionDepart) {
//			actionDepart = false;
//			return;
//		}
		
		if (evt.getActionCommand().equals("comboBoxChanged")){
			// On rajoute la ville precedente
			DefaultListModel model = (DefaultListModel) listeChoixTypeVille.getModel();
			if (villeArriveeCourante != null){
				comboVilleDepart.addItem(villeArriveeCourante);
				model.addElement(villeArriveeCourante);
				
				// On rearrange comboVilleDepart
				String[] c = new String[comboVilleDepart.getItemCount()];
				for (int i=0; i<comboVilleDepart.getItemCount(); i++){
						c[i] = (String) comboVilleDepart.getModel().getElementAt(i);
				}
				java.util.Arrays.sort(c) ;
				
				// On reaffecte la liste
				comboVilleDepart.removeAllItems();
				
				// On supprime la nouvelle ville selectionn�e des listes inter
				DefaultListModel modelInter = (DefaultListModel) listeChoixTypeVilleNon.getModel();
				modelInter.removeElement(villeArriveeCourante);
				modelInter = (DefaultListModel) listeChoixTypeVilleOui.getModel();
				modelInter.removeElement(villeArriveeCourante);
				
				for (int i=0; i<c.length; i++){
					comboVilleDepart.addItem(c[i]);
				}
				
				// On rearrange comboVillesInter
				String[] c2 = new String[model.getSize()];
				for (int i=0; i<model.getSize(); i++){
						c2[i] = (String) model.get(i);
				}
				java.util.Arrays.sort(c2) ;
				
				//on reaffecte la liste
				model.removeAllElements();
				
				for (int i=0; i<c2.length; i++){
					model.addElement(c2[i]);
				}
			}
			
			actionArrivee = true;
			
			//on recupere la nouvelle
			Object val = comboVilleDepart.getItemAt(comboVilleDepart.getSelectedIndex());
			//on l ajoute
			comboVilleDepart.removeItem(val);
			model.removeElement(val);
			//on met a jour la ville courante
			villeArriveeCourante = (String) val;
		}
	}
//	
//	private void sourisVilleDepartClic(java.awt.event.MouseEvent evt) {
//		if (evt.getButton() == java.awt.event.MouseEvent.BUTTON1){
////			on rajoute la ville precedente
//			DefaultListModel model = (DefaultListModel) listeChoixTypeVille.getModel();
//			if (villeDepartCourante != null){
//				comboVilleArrivee.addItem(villeDepartCourante);
//				model.addElement(villeDepartCourante);
//				
//				//on rearrange comboVilleArrivee
//				String[] c = new String[comboVilleArrivee.getItemCount()];
//				for (int i=0; i<comboVilleArrivee.getItemCount(); i++){
//						c[i] = (String) comboVilleArrivee.getModel().getElementAt(i);
//				}
//				java.util.Arrays.sort(c) ;
//				
//				//on reaffecte la liste
//				comboVilleArrivee.removeAllItems();
//				
//				for (int i=0; i<c.length; i++){
//					comboVilleArrivee.addItem(c[i]);
//				}
//				
////				on rearrange comboVillesInter
//				String[] c2 = new String[model.getSize()];
//				for (int i=0; i<model.getSize(); i++){
//						c2[i] = (String) model.get(i);
//				}
//				java.util.Arrays.sort(c2) ;
//				
//				//on reaffecte la liste
//				model.removeAllElements();
//				
//				for (int i=0; i<c2.length; i++){
//					model.addElement(c2[i]);
//				}
//			}
//			//on recupere la nouvelle
//			Object val = comboVilleDepart.getItemAt(comboVilleDepart.getSelectedIndex());
//			//on l ajoute
//			comboVilleArrivee.removeItem(val);
//			model.removeElement(val);
//			//on met a jour la ville courante
//			villeDepartCourante = (String) val;
//		}
//	}
*/

	// Affiche l'�cran de navigation
	private void sourisNav1(java.awt.event.MouseEvent evt) {
		if (evt.getButton() == java.awt.event.MouseEvent.BUTTON1){
			
			if (this.exploiterPrefSimples() && this.panelPrefAvancees.exploiterPrefAvancees()) {
				// Affiche le panneau de navigation rempli avec le nouvel itin�raire
				this.gps.afficheNavigation();
			}
			
		}
	}
	
	public boolean exploiterPrefSimples() {
		// Transmettre les pr�f�rences simples � l'algo de calcul d'itin�raire
		DefaultListModel modelOui = (DefaultListModel) this.listeChoixTypeVilleOui.getModel();
		DefaultListModel modelNon = (DefaultListModel) this.listeChoixTypeVilleNon.getModel();
		
		// Fixer la ville de d�part
		if (this.comboVilleDepart.getSelectedIndex() == -1) {
			JFrame frame = new JFrame("Ville de départ");
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			JOptionPane.showMessageDialog(frame, "Sélectionner une ville de départ");
			return false;
		}
		String nomVilleDepart = (String) this.comboVilleDepart.getSelectedItem();
		this.villeDepartCourante = nomVilleDepart;
		this.gps.controleur.setVilleDepart(this.gps.controleur.getVilles().get(nomVilleDepart));
		
		// Fixer la ville d'arriv�e
		if (this.comboVilleArrivee.getSelectedIndex() == -1) {
			JFrame frame = new JFrame("Ville d'arrivée");
	        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			JOptionPane.showMessageDialog(frame, "Sélectionner une ville d'arrivée");
			return false;
		}
		String nomVilleArrivee = (String) this.comboVilleArrivee.getSelectedItem();
		this.gps.controleur.setVilleArrivee(this.gps.controleur.getVilles().get(nomVilleArrivee));
		
		// Fixer l'itin�raire
		if (this.radioLePlusRapide.isSelected()) {
			this.gps.controleur.setCritereItineraire(new CritereItineraireRapide());
		} else {
			this.gps.controleur.setCritereItineraire(new CritereItineraireCourt());
		}
		
		// Faut-il des �tapes obligatoires?
		if (radioAvec.isSelected()) {
			// Ajouter les etapes obligatoires
			for (int j = 0; j < modelOui.getSize(); j++) {
				String tempPref = (String) modelOui.get(j);
				if (verbose) System.out.println("Ville suivre : " + tempPref);
				this.gps.controleur.addEtapeInterdite(this.gps.controleur.getVilles().get(tempPref));
			}
			
			// Ajouter les etapes interdites
			for (int j = 0; j < modelNon.getSize(); j++) {
				String tempPref = (String) modelNon.get(j);
				if (verbose) System.out.println("Ville éviter : " + tempPref);
				this.gps.controleur.addEtapeObligatoire(this.gps.controleur.getVilles().get(tempPref));
			}
		}
		
		// V�rification du bon ajout des pr�f�rences simples
		System.out.println("VilleArrivee : ");
		System.out.println(" nom=" + this.gps.controleur.getVilleArrivee().getNom());
		System.out.println(" taille=" + this.gps.controleur.getVilleArrivee().getTaille().intitule());
		
		System.out.println("VilleDepart : ");
		System.out.println(" nom=" + this.gps.controleur.getVilleDepart().getNom());
		System.out.println(" taille=" + this.gps.controleur.getVilleDepart().getTaille().intitule());
		
//		CritereEtapes critereEtapesInterdites = this.gps.controleur.getEtapesInterdites();
//		LinkedList<Ville> villesNon = critereEtapesInterdites.getEtapes();
//		System.out.println("Interdites");
//		for (Ville ville : villesNon) {
//			System.out.println(" Ville : " + ville.getNom());
//		}
//		
//		CritereEtapes critereEtapesObligatoires = this.gps.controleur.getEtapesObligatoires();
//		LinkedList<Ville> villesOui = critereEtapesObligatoires.getEtapes();
//		System.out.println("Obligatoires");
//		for (Ville ville : villesOui) {
//			System.out.println(" Ville : " + ville.getNom());
//		}
		
		return true;
	}

	// Affiche l'�cran pr�f�rences avanc�es
	private void sourisPref(java.awt.event.MouseEvent evt) {
		if (evt.getButton() == java.awt.event.MouseEvent.BUTTON1){
			this.gps.affichePrefAvancees(evt);
		}
	}

	private void jRadioButtonSansChanged(javax.swing.event.ChangeEvent evt) {
		if (radioSans.isSelected())	panelVillesInter.setVisible(false);
		else panelVillesInter.setVisible(true);
	}
	
	private void jRadioButtonAvecChanged(javax.swing.event.ChangeEvent evt) {
		if (radioAvec.isSelected()) panelVillesInter.setVisible(true);
		else panelVillesInter.setVisible(false);
	}
	
	
    public class ArrayListTransferHandlerPrefSimples extends TransferHandler {
    	
    	private static final long serialVersionUID = -4387070255003751257L;
    	DataFlavor localArrayListFlavor, serialArrayListFlavor;
        String localArrayListType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList";
        JList source = null;
        int[] indices = null;
        int addIndex = -1; //Location where items were added
        int addCount = 0;  //Number of items added
        private boolean verbose = false;
        
        PanelPrefSimples panelPrefSimples;

        // Le handler conserve une reference sur le panel dans lequel le drag n drop est fait pour
        // des verifications ulterieures
        public ArrayListTransferHandlerPrefSimples(PanelPrefSimples panelPrefSimples) {
        	this.panelPrefSimples = panelPrefSimples;
            try {
                localArrayListFlavor = new DataFlavor(localArrayListType);
            } catch (ClassNotFoundException e) {
                System.out.println("ArrayListTransferHandler: unable to create data flavor");
            }
            serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList");
        }

        public boolean importData(JComponent c, Transferable t) {
            JList target = null;
            ArrayList alist = null;
            if (!canImport(c, t.getTransferDataFlavors())) {
                return false;
            }
            try {
                target = (JList)c;
                if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
                    alist = (ArrayList)t.getTransferData(localArrayListFlavor);
                } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
                    alist = (ArrayList)t.getTransferData(serialArrayListFlavor);
                } else {
                    return false;
                }
            } catch (UnsupportedFlavorException ufe) {
                System.out.println("importData: unsupported data flavor");
                return false;
            } catch (IOException ioe) {
                System.out.println("importData: I/O exception");
                return false;
            }
            
            // On repasse toutes les zones de drop a leur couleur par defaut
            this.panelPrefSimples.listeChoixTypeVille.setBorder(null);
        	this.panelPrefSimples.listeChoixTypeVille.setBackground(Color.WHITE);
        	this.panelPrefSimples.listeChoixTypeVilleOui.setBorder(null);
        	this.panelPrefSimples.listeChoixTypeVilleOui.setBackground(Color.WHITE);
        	this.panelPrefSimples.listeChoixTypeVilleNon.setBorder(null);
        	this.panelPrefSimples.listeChoixTypeVilleNon.setBackground(Color.WHITE);
            
            // On doit v�rifier maintenant qu'il est possible de droper la source dans la target.
            if (verbose) System.out.println(this.panelPrefSimples.listeOrigine);
            if (verbose)  System.out.println(target.getName());
            
            if (this.panelPrefSimples.listeOrigine.equals(this.panelPrefSimples.listeChoixTypeVille.getName())) {
    			if ((!target.getName().equals(this.panelPrefSimples.listeChoixTypeVilleOui.getName()))
    					&& (!target.getName().equals(this.panelPrefSimples.listeChoixTypeVilleNon.getName()))) {
    				if (verbose) System.out.println("deplacement impossible");
    				return false;
    			}
    		}
            
            if (this.panelPrefSimples.listeOrigine.equals(this.panelPrefSimples.listeChoixTypeVilleOui.getName())) {
    			if ((!target.getName().equals(this.panelPrefSimples.listeChoixTypeVille.getName()))
    					&& (!target.getName().equals(this.panelPrefSimples.listeChoixTypeVilleNon.getName()))) {
    				if (verbose) System.out.println("deplacement impossible");
    				return false;
    			}
    		}
            
            if (this.panelPrefSimples.listeOrigine.equals(this.panelPrefSimples.listeChoixTypeVilleNon.getName())) {
    			if ((!target.getName().equals(this.panelPrefSimples.listeChoixTypeVille.getName()))
    					&& (!target.getName().equals(this.panelPrefSimples.listeChoixTypeVilleOui.getName()))) {
    				if (verbose) System.out.println("deplacement impossible");
    				return false;
    			}
    		}
            
            //At this point we use the same code to retrieve the data
            //locally or serially.

            //We'll drop at the current selected index.
            int index = target.getSelectedIndex();

            //Prevent the user from dropping data back on itself.
            //For example, if the user is moving items #4,#5,#6 and #7 and
            //attempts to insert the items after item #5, this would
            //be problematic when removing the original items.
            //This is interpreted as dropping the same data on itself
            //and has no effect.
//            if (source.equals(target)) {
//                if (indices != null && index >= indices[0] - 1 &&
//                      index <= indices[indices.length - 1]) {
//                    indices = null;
//                    return true;
//                }
//            }

            DefaultListModel listModel = (DefaultListModel)target.getModel();
            int max = listModel.getSize();
            if (index < 0) {
                index = max; 
            } else {
                index++;
                if (index > max) {
                    index = max;
                }
            }
            addIndex = index;
            addCount = alist.size();
            for (int i=0; i < alist.size(); i++) {
                listModel.add(index++, alist.get(i));
            }
            return true;
        }

        protected void exportDone(JComponent c, Transferable data, int action) {
            if ((action == MOVE) && (indices != null)) {
                DefaultListModel model = (DefaultListModel)source.getModel();
                
                this.panelPrefSimples.isDragging = false;
                
                //If we are moving items around in the same list, we
                //need to adjust the indices accordingly since those
                //after the insertion point have moved.
                if (addCount > 0) {
                    for (int i = 0; i < indices.length; i++) {
                        if (indices[i] > addIndex) {
                            indices[i] += addCount;
                        }
                    }
                }
                for (int i = indices.length -1; i >= 0; i--)
                    model.remove(indices[i]);
            }
            indices = null;
            addIndex = -1;
            addCount = 0;
        }

        private boolean hasLocalArrayListFlavor(DataFlavor[] flavors) {
            if (localArrayListFlavor == null) {
                return false;
            }

            for (int i = 0; i < flavors.length; i++) {
                if (flavors[i].equals(localArrayListFlavor)) {
                    return true;
                }
            }
            return false;
        }

        private boolean hasSerialArrayListFlavor(DataFlavor[] flavors) {
            if (serialArrayListFlavor == null) {
                return false;
            }

            for (int i = 0; i < flavors.length; i++) {
                if (flavors[i].equals(serialArrayListFlavor)) {
                    return true;
                }
            }
            return false;
        }

        public boolean canImport(JComponent c, DataFlavor[] flavors) {
//        	if (this.panelPrefSimples.isDragging) {
//    			System.out.println("isDragging");
//    			if (this.panelPrefSimples.listeSurvol != null) {
//    				System.out.println(this.panelPrefSimples.listeSurvol.getName());
//    				MouseListener[] zob = this.panelPrefSimples.listeSurvol.getMouseListeners();
//    			}
//    		}
            if (hasLocalArrayListFlavor(flavors))  { return true; }
            if (hasSerialArrayListFlavor(flavors)) { return true; }
            return false;
        }

        protected Transferable createTransferable(JComponent c) {
            if (c instanceof JList) {
                source = (JList)c;
                
                this.panelPrefSimples.origineDragging = source;
                this.panelPrefSimples.isDragging = true;
                String temp = new String(source.getName().getBytes());
                this.panelPrefSimples.listeOrigine = new String(temp.getBytes());
                
                // Eclairer ou on peut dropper
                if (source.equals(this.panelPrefSimples.listeChoixTypeVille)) {
                	this.panelPrefSimples.listeChoixTypeVilleOui.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVilleOui.setBackground(Color.GREEN);
                	this.panelPrefSimples.listeChoixTypeVilleNon.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVilleNon.setBackground(Color.GREEN);
    			}
                if (source.equals(this.panelPrefSimples.listeChoixTypeVilleOui)) {
                	this.panelPrefSimples.listeChoixTypeVille.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVille.setBackground(Color.GREEN);
                	this.panelPrefSimples.listeChoixTypeVilleNon.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVilleNon.setBackground(Color.GREEN);
    			}
                if (source.equals(this.panelPrefSimples.listeChoixTypeVilleNon)) {
                	this.panelPrefSimples.listeChoixTypeVilleOui.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVilleOui.setBackground(Color.GREEN);
                	this.panelPrefSimples.listeChoixTypeVille.setBorder(BorderFactory.createLineBorder(Color.GREEN));
                	this.panelPrefSimples.listeChoixTypeVille.setBackground(Color.GREEN);
    			}
                
                indices = source.getSelectedIndices();
                Object[] values = source.getSelectedValues();
                if (values == null || values.length == 0) {
                    return null;
                }
                ArrayList alist = new ArrayList(values.length);
                for (int i = 0; i < values.length; i++) {
                    Object o = values[i];
                    String str = o.toString();
                    if (str == null) str = "";
                    alist.add(str);
                }
                return new ArrayListTransferable(alist);
            }
            return null;
        }

        public int getSourceActions(JComponent c) {
            return COPY_OR_MOVE;
        }

        public class ArrayListTransferable implements Transferable {
            ArrayList data;

            public ArrayListTransferable(ArrayList alist) {
                data = alist;
            }

            public Object getTransferData(DataFlavor flavor)
                                     throws UnsupportedFlavorException {
            	if (!isDataFlavorSupported(flavor)) {
                    throw new UnsupportedFlavorException(flavor);
                }
                return data;
            }

            public DataFlavor[] getTransferDataFlavors() {
                return new DataFlavor[] { localArrayListFlavor,
                                          serialArrayListFlavor };
            }

            public boolean isDataFlavorSupported(DataFlavor flavor) {
                if (localArrayListFlavor.equals(flavor)) {
                    return true;
                }
                if (serialArrayListFlavor.equals(flavor)) {
                    return true;
                }
                return false;
            }
        }
    }

	public void setReferencePanelPrefAvancees(PanelPrefAvancees panelPrefAvancees) {
		this.panelPrefAvancees = panelPrefAvancees;
	}

    
}
